package com.dragon.common.spring.enhancers.helpers;

import org.springframework.core.MethodParameter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.RequestBody;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Optional;

/**
 * 用于探测方法参数上的RequestBody注解的Helper类
 * 支持从实现类、父类和接口中查找注解
 */
public class RequestBodyDetectionHelper {

    /**
     * 探测方法参数上是否有RequestBody注解（支持接口默认方法）
     */
    public static boolean hasRequestBodyAnnotation(MethodParameter methodParameter) {
        // 1. 首先检查当前方法参数上的注解
        Method method = methodParameter.getMethod();
        Class<?> declaringClass = method.getDeclaringClass();
        if (methodParameter.hasParameterAnnotation(RequestBody.class)) {
            return true;
        }

        // 2. 如果当前方法没有，检查接口默认方法中的对应参数
        if (method != null && method.isDefault()) {
            // 获取接口中声明的方法
            Class<?>[] interfaces = declaringClass.getInterfaces();
            for (Class<?> interfaceClass : interfaces) {
                System.out.println("接口：" + interfaceClass.getName());
                try {
                    Method interfaceMethod = interfaceClass.getMethod(method.getName(), method.getParameterTypes());
                    MethodParameter interfaceParam = new MethodParameter(interfaceMethod, methodParameter.getParameterIndex());
                    if (interfaceParam.hasParameterAnnotation(RequestBody.class)) {
                        return true;
                    }
                } catch (NoSuchMethodException e) {
                    // 接口中没有对应方法，继续检查下一个接口
                    continue;
                }
            }
        }

        // 3. 检查父类中的方法
        Class<?> superClass = declaringClass.getSuperclass();
        if (superClass != null && superClass != Object.class) {
            try {
                Method superMethod = superClass.getMethod(method.getName(), method.getParameterTypes());
                MethodParameter superParam = new MethodParameter(superMethod, methodParameter.getParameterIndex());
                if (superParam.hasParameterAnnotation(RequestBody.class)) {
                    return true;
                }
            } catch (NoSuchMethodException e) {
                // 父类中没有对应方法
            }
        }

        // 4. 深度搜索所有实现的接口（包括继承的接口）
        return hasRequestBodyInInterfaces(method, methodParameter.getParameterIndex());
    }

    /**
     * 深度搜索接口层级结构中的RequestBody注解
     */
    private static boolean hasRequestBodyInInterfaces(Method method, int parameterIndex) {
        return Arrays.stream(method.getDeclaringClass().getInterfaces())
                .anyMatch(interfaceClass -> hasRequestBodyInInterface(interfaceClass, method, parameterIndex));
    }

    /**
     * 在单个接口中查找RequestBody注解
     */
    private static boolean hasRequestBodyInInterface(Class<?> interfaceClass, Method method, int parameterIndex) {
        // 检查当前接口
        try {
            Method interfaceMethod = interfaceClass.getMethod(method.getName(), method.getParameterTypes());
            MethodParameter interfaceParam = new MethodParameter(interfaceMethod, parameterIndex);
            if (interfaceParam.hasParameterAnnotation(RequestBody.class)) {
                return true;
            }
        } catch (NoSuchMethodException e) {
            // 当前接口没有该方法，继续检查父接口
        }

        // 递归检查父接口
        return Arrays.stream(interfaceClass.getInterfaces())
                .anyMatch(parentInterface -> hasRequestBodyInInterface(parentInterface, method, parameterIndex));
    }

    /**
     * 获取RequestBody注解（如果存在）
     */
    public static Optional<RequestBody> getRequestBodyAnnotation(MethodParameter methodParameter) {
        // 1. 首先从当前参数获取
        RequestBody annotation = methodParameter.getParameterAnnotation(RequestBody.class);
        if (annotation != null) {
            return Optional.of(annotation);
        }

        // 2. 从接口默认方法中获取
        Method method = methodParameter.getMethod();
        if (method != null && method.isDefault()) {
            for (Class<?> interfaceClass : method.getDeclaringClass().getInterfaces()) {
                try {
                    Method interfaceMethod = interfaceClass.getMethod(method.getName(), method.getParameterTypes());
                    MethodParameter interfaceParam = new MethodParameter(interfaceMethod, methodParameter.getParameterIndex());
                    RequestBody interfaceAnnotation = interfaceParam.getParameterAnnotation(RequestBody.class);
                    if (interfaceAnnotation != null) {
                        return Optional.of(interfaceAnnotation);
                    }
                } catch (NoSuchMethodException e) {
                    continue;
                }
            }
        }

        return Optional.empty();
    }

    /**
     * 增强的supports方法，用于RequestBodyAdvice
     */
    public static boolean supportsRequestBody(MethodParameter methodParameter, Type targetType,
                                              Class<? extends HttpMessageConverter<?>> converterType) {
        return hasRequestBodyAnnotation(methodParameter);
    }

    /**
     * 获取最准确的MethodParameter（优先返回有注解的那个）
     */
    public static MethodParameter getAnnotatedMethodParameter(MethodParameter originalParameter) {
        if (originalParameter.hasParameterAnnotation(RequestBody.class)) {
            return originalParameter;
        }

        Method method = originalParameter.getMethod();
        if (method != null) {
            int parameterIndex = originalParameter.getParameterIndex();

            // 检查接口
            for (Class<?> interfaceClass : method.getDeclaringClass().getInterfaces()) {
                try {
                    Method interfaceMethod = interfaceClass.getMethod(method.getName(), method.getParameterTypes());
                    MethodParameter interfaceParam = new MethodParameter(interfaceMethod, parameterIndex);
                    if (interfaceParam.hasParameterAnnotation(RequestBody.class)) {
                        return interfaceParam;
                    }
                } catch (NoSuchMethodException e) {
                    continue;
                }
            }

            // 检查父类
            Class<?> superClass = method.getDeclaringClass().getSuperclass();
            if (superClass != null && superClass != Object.class) {
                try {
                    Method superMethod = superClass.getMethod(method.getName(), method.getParameterTypes());
                    MethodParameter superParam = new MethodParameter(superMethod, parameterIndex);
                    if (superParam.hasParameterAnnotation(RequestBody.class)) {
                        return superParam;
                    }
                } catch (NoSuchMethodException e) {
                    // 忽略
                }
            }
        }

        return originalParameter;
    }
}